package com.wtf.config;

import com.wtf.handler.UserClientHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import org.rpc.common.JSONSerializer;
import org.rpc.pojo.RpcRequest;

import java.lang.reflect.Proxy;
import java.util.UUID;

/**
 * desc:
 *
 * @author tengfei wang
 * @version 1.0
 * @date Created in 11/10/2020
 */
public class RpcClient {

    private static UserClientHandler userClientHandler;

    private final String host;
    private final Integer port;

    public RpcClient(String host, Integer port) {
        this.host = host;
        this.port = port;
    }

    public Object createProxy(Class<?> clazz) {
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{clazz}, (proxy, method, args) -> {
            if (userClientHandler == null) {
                initClient();
            }

            //封装请求对象
            RpcRequest rpcRequest = new RpcRequest();
            rpcRequest.setRequestId(UUID.randomUUID().toString());
            rpcRequest.setClassName(clazz.getName());
            rpcRequest.setMethodName(method.getName());
            //设置参数
            if (args != null && args.length > 0) {
                Class[] parameterTypes = new Class[args.length];
                Object[] parameters = new Object[args.length];
                for (int i = 0; i < args.length; i++) {
                    parameterTypes[i] = args[i].getClass();
                    parameters[i] = args[i];
                }
                rpcRequest.setParameters(parameters);
                rpcRequest.setParameterTypes(parameterTypes);
            }

            userClientHandler.setParam(rpcRequest);
            return CustomThreadPool.threadPoolExecutor().submit(userClientHandler).get();
        });
    }

    private void initClient() {
        //实例化userClientHandler
        userClientHandler = new UserClientHandler();
        //创建线程池
        NioEventLoopGroup executors = new NioEventLoopGroup();
        // 创建客服端启动启动引导类
        Bootstrap bootstrap = new Bootstrap();
        // 设置启动引导类
        bootstrap.group(executors).channel(NioSocketChannel.class).handler(new ChannelInitializer() {
            @Override
            protected void initChannel(Channel channel) throws Exception {
                ChannelPipeline pipeline = channel.pipeline();
                // 添加自定义编码器
                pipeline.addLast(new RpcEncoder(RpcRequest.class, new JSONSerializer()));
                pipeline.addLast(new StringDecoder());
                // 添加自定义handler
                pipeline.addLast(userClientHandler);
            }
        });

        try {
            bootstrap.connect(host, port).sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
